import React from "react";

import ReactDOM from "react-dom";

// 定义子组件

class LifeCircle extends React.Component {
  constructor(props) {
    console.log(
      "----------------------16.3开始--------------------------------"
    );
    console.log("进入constructor");

    super(props);

    // state 可以在 constructor 里初始化

    this.state = {
      text: "子组件的文本",
      readyUpdate: "准备被getDerivedStateFromProps更新",
    };
  }

  // 初始化/更新时调用 从props 里 派生 state
  // React 16.4 的挂载和卸载流程都是与 React 16.3 保持一致的，差异在于更新流程上：

  // 在 React 16.4 中，任何因素触发的组件更新流程（包括由 this.setState 和 forceUpdate 触发的更新流程）都会触发 getDerivedStateFromProps；

  // 而在 v 16.3 版本时，只有父组件的更新会触发该生命周期。
  static getDerivedStateFromProps(props, state) {
    console.log("getDerivedStateFromProps方法执行");
    // https://zh-hans.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
    // 代表当前组件接收到的来自父组件的 props 和当前组件自身的 state
    console.log("父级的props", props, "当前组件的state", state);
    return {
      fatherText: props.text,
      newState: "在静态方法getDerivedStateFromProps中创建的state",
      readyUpdate: "定向更新一下readyUpdate",
    };
  }

  // 初始化渲染时调用

  componentDidMount() {
    console.log("componentDidMount方法执行");
  }

  // 组件更新时调用

  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate方法执行");

    return true;
  }

  // 组件更新时调用 render 之后 在真实DOM 更新之前
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate方法执行");

    //     getSnapshotBeforeUpdate 的返回值会作为第三个参数给到 componentDidUpdate。
    //     它的执行时机是在 render 方法之后，真实 DOM 更新之前。
    //     在这个阶段里，我们可以同时获取到更新前的真实 DOM 和更新前后的 state&props 信息。

    // 尽管在实际工作中，需要用到这么多信息的场景并不多，
    // 但在对于实现一些特殊的需求来说，没它还真的挺难办。
    // 这里我举一个非常有代表性的例子：实现一个内容会发生变化的滚动列表，要求根据滚动列表的内容是否发生变化，来决定是否要记录滚动条的当前位置。

    // 这个需求的前半截要求我们对比更新前后的数据（感知变化），
    // 后半截则需要获取真实的 DOM 信息（获取位置），
    // 这时用 getSnapshotBeforeUpdate 来解决就再合适不过了。

    return "haha";
  }

  // 组件更新后调用

  componentDidUpdate(nextProps, nextState, valueFromSnapshot) {
    console.log("componentDidUpdate方法执行");

    console.log("从 getSnapshotBeforeUpdate 获取到的值是", valueFromSnapshot);
  }

  // 组件卸载时调用

  componentWillUnmount() {
    console.log("子组件的componentWillUnmount方法执行");
  }

  // 点击按钮，修改子组件文本内容的方法

  changeText = () => {
    this.setState({
      text: "修改后的子组件文本",
    });
  };

  render() {
    console.log("静态方法执行后的自身的state", this.state);
    console.log("render方法执行");

    return (
      <div className="container">
        <button onClick={this.changeText} className="changeText">
          修改子组件文本内容
        </button>

        <p className="textContent">{this.state.text}</p>

        <p className="fatherContent">{this.props.text}</p>
      </div>
    );
  }
}

// 定义 LifeCycle 组件的父组件

class LifeCircleContainer extends React.Component {
  // state 也可以像这样用属性声明的形式初始化

  state = {
    text: "父组件的文本",

    hideChild: false,
  };

  // 点击按钮，修改父组件文本的方法

  changeText = () => {
    this.setState({
      text: "修改后的父组件文本",
    });
  };

  // 点击按钮，隐藏（卸载）LifeCircle 组件的方法

  hideChild = () => {
    this.setState({
      hideChild: true,
    });
  };

  render() {
    return (
      <div className="fatherContainer">
        <button onClick={this.changeText} className="changeText">
          修改父组件文本内容
        </button>

        <button onClick={this.hideChild} className="hideChild">
          隐藏子组件
        </button>

        {this.state.hideChild ? null : <LifeCircle text={this.state.text} />}
      </div>
    );
  }
}

// ReactDOM.render(<LifeCircleContainer />, document.getElementById("root"));
export default LifeCircleContainer;
